﻿using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using eTMS.Controllers.CTTinhDiemMonHocChiTietService;
using eTMS.Controllers.CTTinhDiemMonHocService;
using eTMS.Controllers.LoaiDiemService;
using System.Runtime.Serialization;

namespace eTMS.Controllers
{
    public class CTTinhDiemMonHocController : CTTinhDiemMonHocControllerBase
    {
        public CTTinhDiemMonHocController()
            : base()
        {
        }
        private DataTable _tblChiTietRemoved;
        private DataTable _tblChiTiet;
        public DataTable TableChiTiet
        {
            get
            {
                return _tblChiTiet;
            }
        }
        public void LoadChiTiet()
        {
            LoadChiTiet(CTTinhDiemMonHocObject.CTTinhDiemMonHoc_ID);
        }
        private void LoadChiTiet(int CT_ID)
        {
            CTTinhDiemMonHocChiTietService.CTTinhDiemMonHocChiTietServiceClient ctTinhDiemMonHocChiTietServiceClient = new CTTinhDiemMonHocChiTietServiceClient();
            _tblChiTiet = ctTinhDiemMonHocChiTietServiceClient.SelectAllDSFilter("CTTinhDiemMonHoc_ID=" + CT_ID.ToString()).Tables[0];
            _tblChiTietRemoved = _tblChiTiet.Clone();
        }
        public void AddNewChiTiet()
        {
            if (_tblChiTiet == null)
            {
                LoadChiTiet(0);
            }
            DataRow row = _tblChiTiet.NewRow();
            row["ThuTuTinh"] = _tblChiTiet.Rows.Count + 1;
            row["LoaiDiemCapNhat_ID"] = 0;
            row["CachTinh"] = 0;
            _tblChiTiet.Rows.Add(row);
        }
        public void RemoveChiTiet(List<DataRow> list)
        {
            if (_tblChiTietRemoved == null) _tblChiTietRemoved = _tblChiTiet.Clone();
            foreach (DataRow row in list)
            {
                _tblChiTietRemoved.ImportRow(row);
                _tblChiTiet.Rows.Remove(row);
            }
        }
        public void SaveDetail()
        {
            CTTinhDiemMonHocChiTietServiceClient ctTinhDiemMonHocChiTietServiceClient =
                new CTTinhDiemMonHocChiTietServiceClient();
            foreach (DataRow row in _tblChiTietRemoved.Rows)
            {
                int ID = ConvertInt(row["CTTinhDiemMonHocChiTiet_ID"]);
                if (ID > 0)
                    ctTinhDiemMonHocChiTietServiceClient.DeleteByID(ID);
            }
            foreach (DataRow row in _tblChiTiet.Rows)
            {
                CTTinhDiemMonHocChiTietEntity chiTietEntity = new CTTinhDiemMonHocChiTietEntity();
                chiTietEntity.CachTinh = ConvertByte(row["CachTinh"]);
                chiTietEntity.CTTinhDiemMonHoc_ID = CTTinhDiemMonHocObject.CTTinhDiemMonHoc_ID;
                chiTietEntity.LoaiDiemCapNhat_ID = ConvertInt(row["LoaiDiemCapNhat_ID"]);
                chiTietEntity.NoiDungCachTinh = row["NoiDungCachTinh"].ToString();
                chiTietEntity.ThuTuTinh = ConvertInt(row["ThuTuTinh"]);
                chiTietEntity.CTTinhDiemMonHocChiTiet_ID = ConvertInt(row["CTTinhDiemMonHocChiTiet_ID"]);
                if (chiTietEntity.CTTinhDiemMonHocChiTiet_ID > 0)
                    ctTinhDiemMonHocChiTietServiceClient.Update(chiTietEntity);
                else
                    ctTinhDiemMonHocChiTietServiceClient.Save(chiTietEntity);
            }
        }
        private Assembly assembly = null;
        public decimal Eval(DataRow row, DataRow rowChiTiet)
        {
            Type type = assembly.GetType("eTMS.Controllers.Math.Score_" + CTTinhDiemMonHocObject.MaCTTinhDiem + "Cal");
            for (int i = 0; i < LoaiDiemController.ListLoaiDiemStatic.Count; i++)
            {
                if (row.Table.Columns.Contains("Col_" + LoaiDiemController.ListLoaiDiemStatic[i].LoaiDiem_ID.ToString()))
                {
                    LoaiDiemEntity loaiDiemEntity = LoaiDiemController.ListLoaiDiemStatic[i];
                    if (!row.IsNull("Col_" + LoaiDiemController.ListLoaiDiemStatic[i].LoaiDiem_ID.ToString()))
                    {

                        type.GetField(loaiDiemEntity.MaLoaiDiem + "_DIEM").SetValue(null, row["Col_" + LoaiDiemController.ListLoaiDiemStatic[i].LoaiDiem_ID.ToString()]);
                    }
                    else
                    {
                        type.GetField(loaiDiemEntity.MaLoaiDiem + "_DIEM").SetValue(null, 0M);
                    }
                }
            }
            return (decimal)type.GetMethod("Cal" + rowChiTiet["CTTinhDiemMonHocChiTiet_ID"].ToString()).Invoke(null, null);
        }
        public void Eval(DataTable tblData)
        {
            foreach (DataRow row in tblData.Rows)
            {
                foreach (DataRow rChitiet in _tblChiTiet.Rows)
                {
                    if (!tblData.Columns.Contains("Col_" + rChitiet["LoaiDiemCapNhat_ID"].ToString()))
                    {
                        tblData.Columns.Add("Col_" + rChitiet["LoaiDiemCapNhat_ID"].ToString());
                    }
                    row["Col_" + rChitiet["LoaiDiemCapNhat_ID"].ToString()] = Eval(row, rChitiet);
                }
            }
        }
        public void ParseCongThuc()
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.AppendLine("namespace eTMS.Controllers.Math{");
            stringBuilder.AppendLine("public class Score_" + CTTinhDiemMonHocObject.MaCTTinhDiem + "Cal{");
            LoaiDiemController.LoadAllLoaiDiem(false);
            foreach (LoaiDiemEntity loaiDiemEntity in LoaiDiemController.ListLoaiDiemStatic)
            {
                stringBuilder.AppendLine("public static decimal " + loaiDiemEntity.MaLoaiDiem + "_DIEM=0;");
                stringBuilder.AppendLine("public static decimal " + loaiDiemEntity.MaLoaiDiem + "_HESO=" + ((double)loaiDiemEntity.HeSo).ToString(System.Globalization.CultureInfo.CurrentUICulture) + "M;");
            }
            foreach (DataRow row in _tblChiTiet.Rows)
            {
                stringBuilder.AppendLine("public static decimal Cal" + row["CTTinhDiemMonHocChiTiet_ID"].ToString() + "()");
                stringBuilder.AppendLine("{");
                stringBuilder.AppendLine("return " + row["NoiDungCachTinh"].ToString().Replace("!", "_") + ";");
                stringBuilder.AppendLine("}");
            }
            stringBuilder.AppendLine("}");
            stringBuilder.AppendLine("}");
            assembly = RuntimeCode.GetAssemblyFromCode(stringBuilder.ToString());
        }




    }
    public class RuntimeCode
    {
        public static Assembly GetAssemblyFromCode(string program)
        {
            string[] Myref = { "System.dll", "System.Data.dll", "System.Drawing.dll", "System.Xml.dll", "CommonControllers.dll", "eTMS.Controllers.dll" };
            
            ICodeCompiler compiler = CodeDomProvider.CreateProvider("C#").CreateCompiler();
            CompilerParameters cp = new CompilerParameters(Myref,null);
            cp.ReferencedAssemblies.Add(typeof(DataContractSerializer).Assembly.Location);
            cp.ReferencedAssemblies.Add(typeof(System.ServiceModel.ServiceHost).Assembly.Location);
            cp.GenerateExecutable = false;            
            cp.GenerateInMemory = true;
            CompilerResults results = compiler.CompileAssemblyFromSource(cp, program);
            if (results.Errors.HasErrors)
            {
                throw new ApplicationException(results.Errors[0].ErrorText);
            }

            Assembly assembly = results.CompiledAssembly;
            return assembly;
        }
        public static Assembly GetAssemblyFromCode(string program, string fileName, bool IsToFile)
        {
            ICodeCompiler compiler = CodeDomProvider.CreateProvider("C#").CreateCompiler();
            CompilerParameters cp = new CompilerParameters();
            cp.GenerateExecutable = false;
            cp.GenerateInMemory = !IsToFile;
            cp.OutputAssembly = fileName;
            CompilerResults results = compiler.CompileAssemblyFromSource(cp, program);
            if (results.Errors.HasErrors)
            {
                throw new ApplicationException(results.Errors[0].ErrorText);
            }

            Assembly assembly = results.CompiledAssembly;
            return assembly;
        }


    }
}